package com.web.portal.controller.user;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.web.portal.config.vo.JwtToken;
import com.web.portal.config.vo.LoginUserVo;
import com.web.portal.pojo.PortalUser;
import com.web.portal.pojo.Relation;
import com.web.portal.pojo.query.PortalUserQuery;
import com.web.portal.pojo.response.NoPasswordUser;
import com.web.portal.pojo.response.PortalUserAndRelation;
import com.web.portal.response.ResponseResult;
import com.web.portal.services.RelationService;
import com.web.portal.services.UserService;
import com.web.portal.utils.ShiroUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

@Slf4j
@RestController
@Api(tags = "用户接口")
@RequestMapping("/user")
public class UserAdminApi {

    @Autowired
    private Gson gson;

    @Autowired// 阔以表明引用哪个类
    private UserService userService;

    @Autowired
    private RelationService relationService;

    @PostMapping("/login")
    @ApiOperation("用户登录")
    public ResponseResult login(String username, String password) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = requestAttributes.getResponse();
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        PortalUser portalUser = userService.selectByUserCode(username);
        if (portalUser == null) {
            return ResponseResult.FAILED("用户存在");
        }
        if (!ShiroUtil.salt(password, portalUser.getSalt()).equals(portalUser.getPassword())) {
            return ResponseResult.FAILED("密码错误");
        }
        if (portalUser.getSalt().equals("0")) {
            return ResponseResult.FAILED("该账号用户已被开除");
        }
        String token = userService.createToken(response, portalUser);
        try {
            JwtToken jwtToken = new JwtToken(token);
            subject.login(jwtToken);
        } catch (UnknownAccountException uae) {
            //如果用户名不存在
            return ResponseResult.FAILED("用户名不存在");
        } catch (IncorrectCredentialsException ice) {
            System.out.println(ice);
            //如果密码错误
            return ResponseResult.FAILED("密码错误");
        }
        LoginUserVo loginUserVo = new LoginUserVo();
        BeanUtils.copyProperties(portalUser, loginUserVo);
        loginUserVo.setToken(token);
        return ResponseResult.SUCCESS("登录成功").setData(loginUserVo);
    }


    /**
     * 获取图灵验证码
     * 有效时长十分钟
     *
     * @return
     */
    @GetMapping("/captcha")
    @ApiOperation("获取图灵验证码")
    public void getCaptcha(HttpServletResponse response, @RequestParam("captcha_key") String captchaKey) {
        try {
            userService.createCaptcha(response, captchaKey);
        } catch (Exception e) {
            log.info(e.toString());
        }
    }


    /**
     * 添加用户
     * 需要管理员权限
     *
     * @param portalUser
     * @return
     */
    @PostMapping
    public ResponseResult addUser(@RequestBody PortalUser portalUser) {
        if (!userService.isAvailable(portalUser)) {
            return ResponseResult.FAILED("权限不够");
        }
        String salt = ShiroUtil.createSalt();
        portalUser.setSalt(salt);
        portalUser.setPassword(ShiroUtil.salt(portalUser.getPassword(), salt));
        boolean flag = userService.save(portalUser);
        if (flag) {
            return ResponseResult.SUCCESS("添加成功");
        } else {
            return ResponseResult.FAILED("添加失败");
        }
    }

    /**
     * 获取用户
     *
     * @param userId
     * @return
     */
    @GetMapping("find_user/{userId}")
    public ResponseResult getUser(@PathVariable("userId") String userId) {
        PortalUser portalUser = userService.getById(userId);

        userService.convertUser(portalUser);

        String user = gson.toJson(portalUser);
        PortalUserAndRelation fromJson = gson.fromJson(user, PortalUserAndRelation.class);

        /**
         * 查找关系
         */
        //构建条件
        QueryWrapper<Relation> wrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(portalUser.getUserCode())) {
            wrapper.eq("user_code", portalUser.getUserCode());
        }
        //调用方法实现分页查询
        List<Relation> relation = relationService.list(wrapper);

        fromJson.setReadable(relation);

        if (portalUser == null) {
            return ResponseResult.FAILED("查找失败");
        }

        return ResponseResult.SUCCESS().setData(fromJson);
    }

    /**
     * 获取分类列表
     * <p>
     * 权限：管理员权限
     *
     * @return
     */
    @GetMapping("find_user/list")
    public ResponseResult listUser() {
//        return ResponseResult.SUCCESS("获取分类列表成功.")
//                .setData(userService.list());
        List<PortalUser> list = userService.list();
        String toJson = gson.toJson(list);
        List<NoPasswordUser> users = gson.fromJson(toJson, new TypeToken<List<NoPasswordUser>>() {
        }.getType());
        return ResponseResult.SUCCESS("获取分类列表成功.")
                .setData(users);
    }

    /**
     * 获取用户
     * <p>
     * 权限：管理员权限
     *
     * @return
     */
    @GetMapping("/{current}/{limit}")
    public ResponseResult findUser(@PathVariable long current,
                                   @PathVariable long limit,
                                   PortalUserQuery portalUserQuery) {
        //创建page对象，传递当前页，每页记录数
        Page<PortalUser> page = new Page<>(current, limit);

        QueryWrapper<PortalUser> wrapper = new QueryWrapper<>();
        wrapper
                .select("id", "user_code", "name", "user_name", "roles", "avatar", "mobile", "sign"
                        , "state", "reg_ip", "login_ip", "create_time", "update_time"
                        , "start_year", "sex", "major")
                .orderByDesc("create_time");
        if (!StringUtils.isEmpty(portalUserQuery.getRoles())) {
            wrapper.eq("roles", portalUserQuery.getRoles());
        }
        if (!StringUtils.isEmpty(portalUserQuery.getSex())) {
            wrapper.eq("sex", portalUserQuery.getSex());
        }
        if (!StringUtils.isEmpty(portalUserQuery.getState())) {
            wrapper.eq("state", portalUserQuery.getState());
        }

        //调用方法实现分页查询
        Page<PortalUser> pageLabelInfo = userService.page(page, wrapper);
        //返回结果
        return ResponseResult.SUCCESS("获取分类列表成功.")
                .setData(pageLabelInfo);
    }


    /**
     * 更新分类
     *
     * @param portalUser
     * @return
     */
    @PostMapping("updateUser")
    public ResponseResult updateUser(@RequestBody PortalUser portalUser) {
        PortalUser checkSobUser = userService.checkSobUser();
        if (!userService.isAvailable(portalUser)
        ) {
            return ResponseResult.FAILED("权限不够");
        }
        boolean flag = userService.updateById(portalUser);
        if (flag) {
            return ResponseResult.SUCCESS("更改成功");
        } else {
            return ResponseResult.FAILED("更改失败");
        }
    }


    @DeleteMapping("/{userId}")
    public ResponseResult deleteUser(@PathVariable("userId") String userId) {
        PortalUser portalUser = userService.getById(userId);
        if (!userService.isAvailable(portalUser)) {
            return ResponseResult.FAILED("权限不够");
        }
        boolean flag = userService.removeById(userId);
        if (flag) {
            return ResponseResult.SUCCESS("删除成功");
        } else {
            return ResponseResult.FAILED("删除失败");
        }
    }

}
